﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace blackhouse.BlackApart.Data {
    public abstract class AdoOpinionsDataAccess : IOpinionsDataAccess {

        #region IOptionsDataAccess Members

        public OpinionCategoryData[] GetOpinionsCategories(string language) {
            return this.ReadOpinionsCategories(this.GetReaderForOpinionsCategories(language));
        }

        public OpinionData GetOpinion(int opinionId) {
            return this.ReadOpinion(this.GetReaderForOpinion(opinionId));
        }

        public Dictionary<int, float> GetOpinionDetails(int opinionId) {
            return this.ReadOpinionDetails(this.GetReaderForOpinionDetails(opinionId));
        }

        public StatisticOpinionData[] GetStatisticOpinionData() {
            return this.ReadStatisticOpinions(this.GetReaderForStatisticOpinion());
        }

        public OpinionData[] GetOpinionsHeader(bool includeNonPublic) {
            return this.ReadOpinions(this.GetReaderForOpinionsHeaders(includeNonPublic));
        }

        public OpinionCategoryValueData[] GetOpinionsDetails(bool includeNonPublic) {
            return this.ReadOpinionsValues(this.GetReaderForOpinionsDetails(includeNonPublic));
        }

        public OpinionTextData[] GetOpinionTextValues(string language) {
            return this.ReadOpinionsTextData(this.GetReaderForOpinionTextValues(language));
        }

        #endregion

        #region Abstracts

        public abstract int SaveOpinion(int opinionId, string inPlusOpinion, string inMinusOpinion, DateTime publishedDate, string publisherCategory, string publisherFirstName, string publisherLastName, string publisherCountry, string language, int userId);
        public abstract int SaveModerateOpinion(int opinionId, string inPlusOpinion, string inMinusOpinion, string answer, int userId);
        public abstract void AddOpinionDetailValue(int opinionId, int categoryId, float val);
        public abstract bool AddOpinionToReservation(int opinionId, int reservationId);
        public abstract int FindReservationToAddOpinion(int apartmentTypeId);
        public abstract void PublishOpinion(int opinionId, int userId);
        public abstract IDataReader GetReaderForOpinionsCategories(string language);
        public abstract IDataReader GetReaderForOpinion(int opinionId);
        public abstract IDataReader GetReaderForOpinionDetails(int opinionId);
        public abstract IDataReader GetReaderForStatisticOpinion();
        public abstract IDataReader GetReaderForOpinionsHeaders(bool includeNonPublic);
        public abstract IDataReader GetReaderForOpinionsDetails(bool includeNonPublic);
        public abstract IDataReader GetReaderForOpinionTextValues(string language);

        #endregion

        #region Methods

        private OpinionTextData[] ReadOpinionsTextData(IDataReader reader) {
            List<OpinionTextData> data = new List<OpinionTextData>();
            while (reader.Read()) {
                data.Add(this.ReadOpinionTextDataFields(reader));
            }
            reader.Close();
            return data.ToArray();
        }

        private OpinionTextData ReadOpinionTextDataFields(IDataReader reader) {
            OpinionTextData data = new OpinionTextData();
            data.PercentTrigger = Convert.ToInt32(reader["TriggerValue"]);
            data.Text = Convert.ToString(reader["Text"]);
            return data;
        }

        private OpinionData ReadOpinion(IDataReader reader) {
            OpinionData data = default(OpinionData);
            if (reader.Read())
                data = this.ReadOpinionFields(reader);
            reader.Close();
            return data;
        }

        private OpinionData[] ReadOpinions(IDataReader reader) {
            List<OpinionData> data = new List<OpinionData>();
            while (reader.Read())
                data.Add(this.ReadOpinionFields(reader));
            reader.Close();
            return data.ToArray();
        }

        private OpinionCategoryData[] ReadOpinionsCategories(IDataReader reader) {
            List<OpinionCategoryData> data = new List<OpinionCategoryData>();
            while (reader.Read()) {
                data.Add(this.ReadOpinionCategoryFields(reader));
            }
            return data.ToArray();
        }

        private OpinionCategoryData ReadOpinionCategoryFields(IDataReader reader) {
            OpinionCategoryData categoryData = new OpinionCategoryData();
            categoryData.CategoryId = Convert.ToInt32(reader["CategoryId"]);
            categoryData.Name = Convert.ToString(reader["Name"]);
            categoryData.NameContinued = Convert.ToString(reader["NameContinued"]);
            return categoryData;
        }

        private OpinionData ReadOpinionFields(IDataReader reader) {
            OpinionData data = new OpinionData();
            data.Id = Convert.ToInt32(reader["Id"]);
            data.InMinusOpinion = Convert.ToString(reader["InMinusOpinion"]);
            data.InPlusOpinion = Convert.ToString(reader["InPlusOpinion"]);
            data.ApartmentType = Convert.ToInt32(reader["ApartmentType"]);
            data.PublishedDate = Convert.ToDateTime(reader["PublishedDate"]);
            data.PublisherCategory = Convert.ToString(reader["PublisherCategory"]);
            data.PublisherCountry = Convert.ToString(reader["PublisherCountry"]);
            data.PublisherFirstName = Convert.ToString(reader["PublisherFirstName"]);
            data.PublisherLastName = Convert.ToString(reader["PublisherLastName"]);
            data.IsPublic = Convert.ToBoolean(reader["IsPublic"]);
            data.Answer = Convert.ToString(reader["Answer"]);
            return data;
        }

        private Dictionary<int, float> ReadOpinionDetails(IDataReader reader) {
            Dictionary<int, float> details = new Dictionary<int, float>();
            while (reader.Read()) {
                KeyValuePair<int, float> detail = this.ReadOpinionDetailFields(reader);
                details.Add(detail.Key, detail.Value);
            }
            return details;
        }

        private KeyValuePair<int, float> ReadOpinionDetailFields(IDataReader reader) {
            return new KeyValuePair<int, float>(Convert.ToInt32(reader["CategoryId"]), Convert.ToSingle(reader["Value"]));
        }

        private StatisticOpinionData[] ReadStatisticOpinions(IDataReader reader) {
            List<StatisticOpinionData> data = new List<StatisticOpinionData>();
            while (reader.Read()) {
                data.Add(this.ReadStatisticOpinionFields(reader));
            }
            return data.ToArray();
        }

        private StatisticOpinionData ReadStatisticOpinionFields(IDataReader reader) {
            StatisticOpinionData data = new StatisticOpinionData();
            data.ApartmentId = Convert.ToInt32(reader["ApartmentId"]);
            data.ApartmentTypeId = Convert.ToInt32(reader["ApartmentTypeId"]);
            data.OpinionCategoryId = Convert.ToInt32(reader["OpinionCategoryId"]);
            data.OpinionId = Convert.ToInt32(reader["OpinionId"]);
            data.PublishedDate = Convert.ToDateTime(reader["PublishedDate"]);
            data.Value = Convert.ToSingle(reader["Value"]);
            data.Language = Convert.ToString(reader["Language"]);
            return data;
        }

        private OpinionCategoryValueData[] ReadOpinionsValues(IDataReader reader) {
            List<OpinionCategoryValueData> data = new List<OpinionCategoryValueData>();
            while (reader.Read()) {
                data.Add(this.ReadOpinionsValuesFields(reader));
            }
            reader.Close();
            return data.ToArray();
        }

        private OpinionCategoryValueData ReadOpinionsValuesFields(IDataReader reader) {
            OpinionCategoryValueData data = new OpinionCategoryValueData();
            data.OpinionId = Convert.ToInt32(reader["OpinionId"]);
            data.CategoryId = Convert.ToInt32(reader["CategoryId"]);
            data.Value = Convert.ToSingle(reader["Value"]);
            return data;
        }

        #endregion

    }
}
